/**
 * @file Field interface
 * @author fanxueliang@qq.com
 */

import type {
    StringSpecItem,
    ColorSpecItem,
    NumberSpecItem,
    BoolSpecItem,
    UploadSpecItem,
    ObjectSpecItem,
    ListSpecItem,
    HtmlSpecItem,
    UrlSpecItem,
    AlternativeSpecItem,
    EnumSpecItem,
    VideoUploadSpecItem,
    AudioUploadSpecItem,
    ExpressionProps
} from './spec';
import type {ValidateFunType} from '../validator';
import type {Datasource, ColorConfigAttr, ExtensionsAttr, CustomObject} from './extraAttr';

export type StringLikeField =
    | StringField
    | InputField
    | UrlField
    | RichTextField
    | TextareaField
    | SearchBoxField
    | ImageUploaderField
    | VideoUploaderField
    | AudioUploaderField
    | SelectStringField
    | RadioButtonGroupStringField;
export type NumberLikeField = SelectNumberField | NumberInputField;
export type BoolLikeField = SwitchField | CheckboxField;
export type ObjectLikeField = ObjectField | NormalObjectField | SelectObjectField;
export type ListLikeField = NormalListField;
export type LikeFieldType =
    | StringLikeField
    | ColorPickerField
    | NumberLikeField
    | BoolLikeField
    | ObjectLikeField
    | ListLikeField;

export interface FieldValidateResultType {
    errors: string[];
    warnings: string[];
    successTips: string[];
}

export interface BasicField {
    // 显示，数据需要校验 & 提交
    display?: string;
    // 只读，数据需要校验 & 提交
    readOnly?: boolean;
    // 展示但是只读，并且数据不需要校验 & 提交
    disabled?: boolean;
    // 验证中状态
    validating?: boolean;
    // 比较value 与 initValue 是否一致
    modified?: boolean;
    value?: any;
    initialValue?: any;
    name: string;
    displayName?: string;
    path: string;
    idx?: string;
    isLeaf?: boolean;
    showIndex: number;
    validateResult?: FieldValidateResultType;
    validators?: ValidateFunType[];
    extensions?: ExtensionsAttr[];
    reactions?: CustomObject;
    nameTip?: string;
    tip?: string;
    descriptionTip?: string;
    required?: boolean;
    hidden?: string | ExpressionProps[];
    remove?: string | ExpressionProps[];
    slots?: CustomObject[];
}

export interface FieldDatasource extends Datasource {
    hidden?: string | ExpressionProps[];
}

export interface StringField extends BasicField {
    type: 'STRING';
    spec:
        | StringSpecItem
        | EnumSpecItem
        | UploadSpecItem
        | VideoUploadSpecItem
        | AudioUploadSpecItem
        | HtmlSpecItem
        | UrlSpecItem;
    component?: string;
}

export interface InputField extends StringField {
    component: 'Input';
    spec: StringSpecItem;
}

export interface UrlField extends StringField {
    component: 'Input';
    spec: UrlSpecItem;
}

export interface TextareaField extends StringField {
    component: 'Textarea';
    spec: StringSpecItem;
}

export interface RichTextField extends StringField {
    component: 'RichText';
    spec: HtmlSpecItem;
}

export interface SearchBoxField extends StringField {
    component: 'SearchBox';
    spec: StringSpecItem;
    datasource: string[];
}

export interface ColorPickerField extends BasicField, ColorConfigAttr {
    type: 'COLOR';
    component: 'Color';
    spec: ColorSpecItem;
}

export interface ImageUploaderField extends StringField {
    component: 'Uploader';
    spec: UploadSpecItem;
}

export interface VideoUploaderField extends StringField {
    component: 'VideoUploader';
    spec: VideoUploadSpecItem;
}

export interface AudioUploaderField extends StringField {
    component: 'AudioUploader';
    spec: AudioUploadSpecItem;
}

export interface SelectStringField extends StringField {
    component: 'EnumSelect';
    spec: EnumSpecItem;
    datasource: FieldDatasource[];
}

export interface RadioButtonGroupStringField extends StringField {
    component: 'RadioButtonGroup';
    datasource: FieldDatasource[];
}

export interface NumberInputField extends BasicField {
    component: 'NumberInput';
    type: 'NUMBER';
    spec: NumberSpecItem;
}

export interface SelectNumberField extends BasicField {
    component: 'Select';
    type: 'NUMBER';
    spec: EnumSpecItem;
    datasource: FieldDatasource[];
}

export interface BoolField extends BasicField {
    type: 'BOOL';
    spec: BoolSpecItem;
    component?: string;
}

export interface CheckboxField extends BoolField {
    component: 'Checkbox';
}

export interface SwitchField extends BoolField {
    component: 'Switch';
}

export interface ObjectField extends BasicField {
    type: 'OBJECT';
    component?: string;
    spec: ObjectSpecItem;
    children: LikeFieldType[];
}

export interface NormalObjectField extends ObjectField {
    component: 'Block';
    datasource: FieldDatasource[];
    spec: ObjectSpecItem;
    children: LikeFieldType[];
}

export interface SelectObjectField extends BasicField {
    type: 'OBJECT';
    component: 'Select';
    datasource: FieldDatasource[];
    children: LikeFieldType[];
    spec: AlternativeSpecItem;
}

export interface RadioButtonGroupObjectField extends ObjectField {
    component: 'RadioButtonGroup';
    datasource: FieldDatasource[];
    spec: ObjectSpecItem;
    children: LikeFieldType[];
}

export interface ListField extends BasicField {
    type: 'LIST';
    component?: string;
    spec: ListSpecItem;
    hasVirtualBlock?: boolean;
}

export interface NormalListField extends ListField {
    component: 'List';
    children: LikeFieldType[];
}

export interface TabsField extends ListField {
    component: 'Tabs';
    children: LikeFieldType[];
}
